/*
 *
 * This file is part of the open-source SeetaFace engine, which includes three modules:
 * SeetaFace Detection, SeetaFace Alignment, and SeetaFace Identification.
 *
 * This file is part of the SeetaFace Detection module, containing codes implementing the
 * face detection method described in the following paper:
 *
 *
 *   Funnel-structured cascade for multi-view face detection with alignment awareness,
 *   Shuzhe Wu, Meina Kan, Zhenliang He, Shiguang Shan, Xilin Chen.
 *   In Neurocomputing (under review)
 *
 *
 * Copyright (C) 2016, Visual Information Processing and Learning (VIPL) group,
 * Institute of Computing Technology, Chinese Academy of Sciences, Beijing, China.
 *
 * The codes are mainly developed by Shuzhe Wu (a Ph.D supervised by Prof. Shiguang Shan)
 *
 * As an open-source face recognition engine: you can redistribute SeetaFace source codes
 * and/or modify it under the terms of the BSD 2-Clause License.
 *
 * You should have received a copy of the BSD 2-Clause License along with the software.
 * If not, see < https://opensource.org/licenses/BSD-2-Clause>.
 *
 * Contact Info: you can send an email to SeetaFace@vipl.ict.ac.cn for any problems.
 *
 * Note: the above information must be kept whenever or wherever the codes are used.
 *
 */

#include "surf_mlp_model_reader.h"

//#include <istream>

#include "surf_mlp.h"

void InitSURFMLPModelReader(struct classSURFMLPModelReader *p)
{

}

bool SURFMLPModelReaderRead(struct classSURFMLPModelReader *p, FILE* input, SURFMLP* model) {
  bool is_read = false;
  SURFMLP* surf_mlp = (SURFMLP*)(model);
  int32_t num_layer;
  int32_t num_feat;
  int32_t input_dim;
  int32_t output_dim;
  float thresh;
  int i;
  fread((char*)(&num_layer), sizeof(int32_t),1,input);
  if (num_layer <= 0) {
    is_read = false;  // @todo handle the errors and the following ones!!!
  }
  fread((char*)(&num_feat), sizeof(int32_t),1,input);
  if (num_feat <= 0) {
    is_read = false;
  }

  //p->feat_id_buf_.resize(num_feat);
  p->feat_id_buf_ = (int32_t*)malloc(sizeof(int32_t)*num_feat);
  surf_mlp->feat_id_ = (int32_t*)malloc(sizeof(int32_t)*num_feat);
  fread(p->feat_id_buf_, sizeof(int32_t) , num_feat,input);
  for ( i = 0; i < num_feat; i++)
	  SURFMLPAddFeatureByID(surf_mlp, p->feat_id_buf_[i],i);

  fread((char*)(&thresh), sizeof(float),1,input);
  SURFMLPSetThreshold(surf_mlp, thresh);
  fread((char*)(&input_dim), sizeof(int32_t),1,input);
  if (input_dim <= 0) {
    is_read = false;
  }
  surf_mlp->mlp.layers_ = (MLPLayer*)malloc(sizeof(MLPLayer)*(num_layer - 1));
  for ( i = 1; i < num_layer; i++) {
    fread((char*)(&output_dim), sizeof(int32_t),1,input);
    if (output_dim <= 0) {
      is_read = false;
    }

    int32_t len = input_dim * output_dim;
   // p->weights_buf_.resize(len);
	p->weights_buf_ = (float*)malloc(sizeof(float)*len);
    fread(p->weights_buf_, sizeof(float) , len,input);

   // p->bias_buf_.resize(output_dim);
	p->bias_buf_ = (float*)malloc(sizeof(float)*output_dim);
    fread(p->bias_buf_, sizeof(float) , output_dim,input);

    if (i < num_layer - 1) {
		SURFMLPAddLayer(surf_mlp, input_dim, output_dim, p->weights_buf_,
        p->bias_buf_, i,false);
    } else {
		SURFMLPAddLayer(surf_mlp, input_dim, output_dim, p->weights_buf_,
        p->bias_buf_,i, true);
    }
    input_dim = output_dim;
  }

  int layerbufLen = MLPLayerGetOutputDim(&surf_mlp->mlp.layers_[0]);
  surf_mlp->mlp.layer_buf_[0] = (float*)malloc(sizeof(float)*layerbufLen);
  int layerLen = MLPGetLayerNum(&surf_mlp->mlp);
  for ( i = 1; i < layerLen - 1; i++) {
	  layerbufLen = MLPLayerGetOutputDim(&surf_mlp->mlp.layers_[i]);
	  surf_mlp->mlp.layer_buf_[i % 2] = (float*)malloc(sizeof(float)*layerbufLen);
  }

  is_read = !(input == NULL);

  return is_read;
}

